home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1998 September / Macworld (1998-09).dmg / Shareware World / Info / For Developers / MacZoop 1.8.3 / More Classes / Threads / ZThread.cp < prev    next >
Text File  |  1996-11-26  |  5KB  |  259 lines

  1. /*************************************************************************************************
  2. *
  3. *
  4. *            ObjectMacZapp        -- a standard Mac OOP application template
  5. *
  6. *
  7. *
  8. *            ZThread.cpp            -- an object that implements a single thread of execution
  9. *
  10. *
  11. *
  12. *
  13. *
  14. *            © 1996, Graham Cox
  15. *
  16. *
  17. *
  18. *
  19. *************************************************************************************************/
  20.  
  21.  
  22. #include     "ZThread.h"
  23. #include    "ZThreadedApplication.h"
  24.  
  25.  
  26.  
  27. // Constructor
  28. ZThread::ZThread( long doPeriod, Size stackSize )
  29. {
  30.     // Initialiase data members
  31.     fDone = FALSE;
  32.     itsID = kNoThreadID;
  33.     itsStack = stackSize;
  34.     itsPeriod = doPeriod;    
  35. }                        
  36.     
  37.  
  38. // Destructor        
  39. ZThread::~ZThread()
  40. {
  41.     // If the thread is running then kill it
  42.     if( itsID != kNoThreadID )
  43.     {
  44.         Terminate();
  45.     }
  46. }                                    
  47.  
  48.  
  49. // ThreadEntry()
  50. void ZThread::ThreadEntry()
  51. {
  52.     while( !IsDone() )
  53.     {
  54.          // Call Do()
  55.          Do();
  56.      
  57.          // and then sleep for itsPeriod ticks 
  58.          SleepTicks( itsPeriod );
  59.      }
  60.      
  61.      itsID = kNoThreadID;
  62.  }    
  63.  
  64.      
  65. // IsDone()
  66. inline Boolean ZThread::IsDone()
  67. {
  68.     return fDone;
  69. }
  70.  
  71.  
  72. // SetDoPeriod()
  73. void ZThread::SetDoPeriod( long doPeriod )
  74. {
  75.     itsPeriod = doPeriod;
  76. }
  77.  
  78.  
  79. // Start
  80. void ZThread::Start()
  81. {
  82.     // If we already have a thread but it's just stopped, call restart
  83.     if( itsID != kNoThreadID )
  84.     {
  85.         Restart();
  86.     }
  87.     else
  88.     {
  89.         // Get a new thread
  90.         FailOSErr( NewThread(     kCooperativeThread,
  91.                                 (ThreadEntryProcPtr)(&ThreadEntryGlue),
  92.                                  this,
  93.                                  itsStack,
  94.                                  kCreateIfNeeded,
  95.                                  NULL,
  96.                                  &itsID ) );
  97.  
  98.         // Install our custom context switchers...
  99.  
  100.         // ... before we're switched in...
  101.         FailOSErr( SetThreadSwitcher( itsID, (ThreadSwitchProcPtr)(&SwitchingInGlue), this, TRUE ) ); 
  102.  
  103.         // ... and before we're switched out
  104.         FailOSErr( SetThreadSwitcher( itsID, (ThreadSwitchProcPtr)(&SwitchingOutGlue), this, FALSE ) ); 
  105.     }
  106. }                     
  107.  
  108.  
  109. // Stop()
  110. OSErr ZThread::Stop()
  111. {                    
  112.     if( gMacHasThreadManager )
  113.     {
  114.         return SetThreadState( itsID, kStoppedThreadState, kNoThreadID ); 
  115.     }
  116.     else
  117.     {
  118.         return paramErr;
  119.     }
  120. }
  121.  
  122.  
  123. // Restart()    
  124. OSErr ZThread::Restart()
  125. {
  126.     if( gMacHasThreadManager )
  127.     {
  128.         return SetThreadState( itsID, kReadyThreadState, kNoThreadID );     
  129.     }
  130.     else
  131.     {
  132.         return paramErr;
  133.     }
  134. }        
  135.  
  136.  
  137. // Terminate()
  138. void ZThread::Terminate( Boolean fReturnToPool )
  139. {                    
  140.     // Stop the thread
  141.     Stop();
  142.     
  143.     if( gMacHasThreadManager )
  144.     {
  145.         // Dispose of it
  146.         DisposeThread( itsID, NULL, fReturnToPool );
  147.     }
  148.  
  149.     // Set itsID so that we can't do anything else to this thread
  150.     itsID = kNoThreadID;
  151. }
  152.  
  153.  
  154. // GetState() returns current thread state in *pState
  155. // The states are defined in Threads.h but can be a bit confusing.
  156. //
  157. // Basically my understanding is:
  158. //
  159. // - kReadyThreadState means that the thread is ready to run but is not the current
  160. //   thread.  Normal running threads will return this if GetState() is called from
  161. //   another thread.
  162. //
  163. // - kStoppedThreadState means that the thread has been stopped by a Stop() instruction.
  164. //
  165. // - kRunningThreadState means that the thread is running *and* is the current thread.
  166. //   GetState() will return this if it's called from within Do() say.
  167. //
  168. ThreadState ZThread::GetState()
  169. {
  170.     if( (itsID != kNoThreadID) && gMacHasThreadManager )
  171.     {
  172.         ThreadState state;
  173.         FailOSErr( GetThreadState( itsID, &state ) );
  174.         return state;
  175.     }
  176.     else
  177.     {
  178.         return kStoppedThreadState;
  179.     }
  180. }
  181.  
  182.  
  183. // SleepTicks()
  184. void ZThread::SleepTicks( long ticksToSleep )
  185. {
  186.     long lSleepTicks = TickCount() + ticksToSleep;
  187.     
  188.     if( gMacHasThreadManager )
  189.     {
  190.         do {
  191.             YieldToAnyThread();
  192.         } while( TickCount() < lSleepTicks );
  193.     }
  194. }
  195.     
  196.  
  197. // Glue functions not part of ZThread
  198.  
  199. /******************************************************************************
  200.  ThreadEntryGlue
  201.  ******************************************************************************/
  202.  
  203. pascal void * ThreadEntryGlue( ZThread* me )
  204. {
  205.     // Trap exceptions - if an exception runs off the top of the
  206.     // thread stack we'll be in *real* trouble!
  207.     try
  208.     {
  209.         me->ThreadEntry();
  210.     }
  211.     catch(OSErr err)
  212.     {
  213.     }
  214.     
  215.     return NULL;
  216. }  
  217.  
  218. /******************************************************************************
  219.  SwitchingInGlue
  220.  ******************************************************************************/
  221.  
  222. pascal void SwitchingInGlue( ThreadID threadBeingSwitched, ZThread* me )
  223. {
  224.     me->SwitchingIn();
  225. }  
  226.  
  227. /******************************************************************************
  228.  SwitchingOutGlue
  229.  ******************************************************************************/
  230.  
  231. pascal void SwitchingOutGlue( ThreadID threadBeingSwitched, ZThread* me )
  232. {
  233.     me->SwitchingOut();
  234. }  
  235.  
  236.  
  237. // Utility function - yield for lTicks ticks
  238. void YieldTicks( long lTicks )
  239. {
  240.     if( gMacHasThreadManager )
  241.     {
  242.         long targetTicks = TickCount() + lTicks;
  243.         while( TickCount() < targetTicks )
  244.         {
  245.             YieldToAnyThread();
  246.         }
  247.     }
  248. }
  249.  
  250.  
  251. // Utility function - safe yield
  252. void SafeYield()
  253. {
  254.     if( gMacHasThreadManager )
  255.         YieldToAnyThread();
  256. }
  257.  
  258.  
  259.